import CryptoJS from "crypto-js";
import type {UFile} from "@/util/definition";

//数组转成crypto加密可以使用的数据格式
const arrayBufferToWordArray = function (arrayBuffer: ArrayBuffer): CryptoJS.lib.WordArray {
    let i8a = new Uint8Array(arrayBuffer);
    let a = [];
    for (let i = 0; i < i8a.length; i += 4) {
        a.push(i8a[i] << 24 | i8a[i + 1] << 16 | i8a[i + 2] << 8 | i8a[i + 3]);
    }
    return CryptoJS.lib.WordArray.create(a, i8a.length);
}

class ExtReader extends FileReader {
    loadNext(
        uFile: UFile,
        currentChunk: number,
    ): void {
        const blobSlice =
            File.prototype.slice;
        const start = currentChunk * uFile.chunkSize;
        const end = start + uFile.chunkSize >= uFile.size ? uFile.size : start + uFile.chunkSize;
        this.readAsArrayBuffer(blobSlice.call(uFile, start, end));
    }
}

interface OptinoCallback {
    onProgress: Function;
    onSuccess: Function;
    onError: Function;
}

/**
 * 分片计算文件的sha256
 * @param uFile vue-simple-uploader的文件对象
 * @param options 回调方法参数 onProgress(uFile,currentChunk,chunkSize) | onSuccess(uFile,sha256) | onError(uFile,chunkSize)
 */
const calSha256 = (uFile: UFile, options?: OptinoCallback): void => {
    const fileReader = new ExtReader();
    let currentChunk = 0;
    const chunks = uFile.totalChunks; //总的片数
    const sha256Process = uFile.hasher;
    if (sha256Process) {
        fileReader.loadNext(uFile, currentChunk);
        fileReader.onload = (e) => {
            // @ts-ignore
            const tmpWordArray = arrayBufferToWordArray(e.target.result);
            //@ts-ignore
            sha256Process.update(tmpWordArray);
            if (currentChunk < chunks) {
                currentChunk++;
                fileReader.loadNext(uFile, currentChunk);
                // 实时展示SHA256的计算进度
                if (options && options.onProgress) {
                    options.onProgress(uFile, currentChunk);
                }
            } else {
                //@ts-ignore
                const sha256 = sha256Process.finalize().toString(CryptoJS.enc.Hex);
                uFile.uniqueIdentifier = sha256; //把sha256赋值给上传参数
                if (options && options.onSuccess) {
                    options.onSuccess(uFile, sha256)
                }
            }
        };
        fileReader.onerror = () => {
            if (options && options.onError) {
                options.onError(uFile);
            }
            // uFile.cancel();
        };
    }
}
export {arrayBufferToWordArray, ExtReader, calSha256};
export type {OptinoCallback};